/**
 * LoginAction.java
 * Created at 2016-5-5
 * Created by Tangsanlin
 * Copyright (C) 2016 BROADTEXT SOFTWARE, All rights reserved.
 */
package com.broadtext.rms.system.action;

import com.alibaba.fastjson.JSONArray;
import com.broadtext.common.annotation.SystemControllerLog;
import com.broadtext.common.exp.DaoException;
import com.broadtext.common.exp.ServiceException;
import com.broadtext.common.utils.MD5Util;
import com.broadtext.common.utils.StrUtil;
import com.broadtext.common.utils.StringUtils;
import com.broadtext.rms.session.LoginResult;
import com.broadtext.rms.session.LoginState;
import com.broadtext.rms.session.SessionManage;
import com.broadtext.rms.session.UserSession;
import com.broadtext.rms.system.model.SysResource;
import com.broadtext.rms.system.model.SysRole;
import com.broadtext.rms.system.model.SysUser;
import com.broadtext.rms.system.model.VSysUsers;
import com.broadtext.rms.system.service.ILoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.net.InetAddress;
import java.util.*;

/**
 * 
 * <p>
 * ClassName: LoginAction
 * </p>
 * <p>
 * Description: 用户登录
 * </p>
 * <p>
 * Author: Administrator
 * </p>
 * <p>
 * Date: 2016-4-22
 * </p>
 */
@Controller
public class LoginAction {
    /**
     * 登录服务
     */
    @Autowired
    @Qualifier("loginService")
    private ILoginService loginService;
    
    /**
     * 登陆用户缓存池
     */
    private static final Map<String, String> UserPool = new HashMap<String, String>();

    /**
     * 用户登录，
     * 
     * @param request 请求信息
     * @param response 响应信息
     * @return 登录信息
     * @throws Exception 异常
     */
    @SystemControllerLog(description = "login") 
    @RequestMapping(value = "/main/login.mvc")
    @ResponseBody
    public Map<String, String> login(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView view;
        view = new ModelAndView();
        String loginName;
        loginName = new String(request.getParameter("loginName"));
        String loginPassword;
        loginPassword = request.getParameter("loginPassword");
        VSysUsers vUser;
        vUser = this.loginService.findVuser(loginName);
        Map<String, String> map;
        map = new HashMap<String, String>();
        if (vUser == null) {
            map.put("msg", LoginResult.LOGINNAMENOTFOUND.getContext());
            return map;
        } else if (vUser.getIsLock().equals("1")) {
            //用户状态为锁定
            map.put("msg", LoginResult.LOGINUSERISLOCKED.getContext());
            return map;
        } 
        //校验账户期限
        if(!this.loginService.getAccountValidity(loginName)){
            map.put("msg", LoginResult.ACCOUNTEXPIRED.getContext());
            return map;
        }
        String password;
        password=vUser.getPass();
        String pass;
        pass = MD5Util.getDigest(loginPassword);
        if (!pass.equals(password)) {
            view.setViewName("login");
            view.addObject("msg", LoginResult.ERRORPASSWORD.getContext());
            map.put("msg", LoginResult.LOGINNAMENOTFOUND.getContext());
            return map;
        }
        String ip = this.getIpAddress(request);
        if (this.checkLoginSeize(ip, loginName)) {
            map.put("msg", LoginResult.CHECKOK.getContext());
        } else {
            HttpSession currentSession;
            currentSession = request.getSession();
            UserSession userSession;
            userSession = SessionManage.getSessionManage().getUserSession(currentSession);
            if (userSession == null) {
                userSession = new UserSession(currentSession);
            }
            loadUserSession(vUser, userSession, request);
            currentSession.setAttribute(SessionManage.USERSESSION, userSession);
            SessionManage.getSessionManage().getUserSessions().put(currentSession.getId(), currentSession);
            killExistsSession(currentSession, vUser.getPkId());
            LoginAction.UserPool.put(loginName, ip);
            map.put("msg", LoginResult.LOGINOK.getContext());
        }
        return map;
    }
    
    /**
     * 
     * <p>Description: 创建登陆session</p>
     * @param request 请求对象
     * @param response 返回对象
     * @return 操作标志
     * @throws Exception 异常
     */
    @RequestMapping(value = "/main/loginSession.mvc")
    @ResponseBody
    public Map<String, String> loginSession(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, String> map;
        map = new HashMap<String, String>();
        String loginName;
        loginName = new String(request.getParameter("loginName").getBytes("iso-8859-1"), "utf-8");
        VSysUsers vUser;
        vUser = this.loginService.findVuser(loginName);
        HttpSession currentSession;
        currentSession = request.getSession();
        UserSession userSession;
        userSession = SessionManage.getSessionManage().getUserSession(currentSession);
        if (userSession == null) {
            userSession = new UserSession(currentSession);
        }
        loadUserSession(vUser, userSession, request);
        currentSession.setAttribute(SessionManage.USERSESSION, userSession);
        SessionManage.getSessionManage().getUserSessions().put(currentSession.getId(), currentSession);
        killExistsSession(currentSession, vUser.getPkId());
        String ip = this.getIpAddress(request);
        System.out.println(LoginAction.UserPool.size());
        LoginAction.UserPool.put(loginName, ip);
        map.put("msg", LoginResult.LOGINOK.getContext());
        return map;
    }

    /**
     * <p>Description: 得到客户端IP</p>
     * @param request 请求信息
     * @return ip
     * @throws Exception 异常
     */
    private String getIpAddress(HttpServletRequest request) throws Exception {
        String ipAddress; 
        ipAddress = request.getHeader("X-Forwarded-For");   
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {   
            ipAddress = request.getHeader("Proxy-Client-IP");   
        }   
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {   
            ipAddress = request.getHeader("WL-Proxy-Client-IP");   
        }   
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {   
            ipAddress = request.getRemoteAddr();   
            if ("127.0.0.1".equals(ipAddress)) {
                InetAddress inet;  
                inet = InetAddress.getLocalHost();   
                ipAddress = inet.getHostAddress();   
            }  
        }   
        //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割   
        if (ipAddress != null && ipAddress.indexOf(",") > 0) {
            ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));   
        }
        return ipAddress;
    }

    /**
     * 
     * <p>
     * Description: 加载用户Session信息
     * </p>
     * 
     * @param vUser 登录用户信息
     * @param userSession 用户ssession
     * @param request 请求信息
     * @throws DaoException 
     */
    private void loadUserSession(VSysUsers vUser, UserSession userSession, HttpServletRequest request) 
        throws DaoException {
        HttpSession httpSession;
        httpSession = request.getSession(false);

        httpSession.setAttribute("sys.user", vUser.getPkId());
        httpSession.setAttribute("sys.userName", vUser.getLoginName());
        httpSession.setAttribute("sys.dispName", vUser.getEmpName());

        userSession.setUserId(vUser.getPkId());
        userSession.setDispName(vUser.getEmpName());
        userSession.setLoginName(vUser.getLoginName());
        userSession.setLoginTime(new Date());
        userSession.setUserName(vUser.getLoginName());
        //2017-08-23 session中添加角色引导页
        userSession.setHomePage(vUser.getHomePage());
        userSession.setShowMessage(vUser.getShowMessage());
        
        List<SysRole> roleList;
        roleList = new ArrayList<SysRole>(); 
        roleList = this.loginService.selectRoleByUserId(vUser.getPkId());
        String[] roleIds;
        roleIds = new String[roleList.size()];
        int i = 0;
        for (SysRole r : roleList) {
            roleIds[i] = r.getPkId();
            i++;
        }
        userSession.setHavRoleIds(roleIds);
        SysResource[] res;
        res = this.loginService.getHavResByLoginName(vUser.getLoginName());
        String[] resCodes;
        resCodes = new String[res.length];
        for (i = 0; i < res.length; i++) {
            resCodes[i] = res[i].getResUrl();
        }
        userSession.setHavResCodes(resCodes);
        userSession.setLoginState(LoginState.LOGIN);
    }

    /**
     * kill掉session中存在userId的session
     * 
     * @param currentSession 用户session
     * @param userId 用户ID
     */
    private void killExistsSession(HttpSession currentSession, String userId) {
        SessionManage sessionManage;
        sessionManage = SessionManage.getSessionManage();
        Map<String, HttpSession> sessions;
        sessions = sessionManage.getUserSessions();
        for (Map.Entry<String, HttpSession> entry : sessions.entrySet()) {
            HttpSession session;
            session = entry.getValue();
            UserSession userSesssion;
            userSesssion = sessionManage.getUserSession(session);
            if (userSesssion != null && userId.equals(userSesssion.getUserId())) {
                if (!currentSession.getId().equals(session.getId())) {
                    session.removeAttribute(SessionManage.USERSESSION);
                }
            }
        }
    }

    /**
     * 
     * <p>
     * Description: 注销登录
     * </p>
     * 
     * @param request 请求信息
     * @param response 响应信息
     * @return view 登录页面
     * @throws Exception 异常
     */
    @SystemControllerLog(description = "logout")
    @RequestMapping(value = "/main/loginOut.mvc")
    public void loginOut(HttpServletRequest request, HttpServletResponse response) throws Exception {
        SessionManage sessionManage;
        sessionManage = SessionManage.getSessionManage();
        Map<String, HttpSession> sessions;
        sessions = sessionManage.getUserSessions();
        HttpSession currentSession;
        currentSession = request.getSession(false);
        
        Map<String, String> map;
        map = new HashMap<String, String>();
        map.put("msg", LoginState.LOGOUT.getContext());
        
        for (Map.Entry<String, HttpSession> entry : sessions.entrySet()) {
            HttpSession session;
            session = entry.getValue();
            if (currentSession.getId().equals(session.getId())) {
                String loginName = String.valueOf(session.getAttribute("sys.userName"));
                if (!this.checkLoginSeize(this.getIpAddress(request), loginName)) {
                    LoginAction.UserPool.remove(loginName);
                }
                session.removeAttribute(SessionManage.USERSESSION);
                //销毁当前session
                session.invalidate();
            }
        }
    }

    /**
     * 
     * <p>
     * Description: 跳转到对应的页面
     * </p>
     * 
     * @param request 请求信息
     * @param response 响应信息
     * @return view 登录页面
     * @throws Exception 异常
     */
    @RequestMapping(value = "/forwardPage.mvc")
    public ModelAndView forwardPage(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView view;
        view = new ModelAndView();
        String page;
        page = request.getParameter("page");
        if (page == null) {
            page = "login";
        } else {
            if ("index".equals(page)) {
                UserSession userSession;
                userSession = SessionManage.getSessionManage().getUserSession(request.getSession(false));
                view.addObject("displayName", userSession.getDispName());
                view.addObject("organName", userSession.getOrganName());
                view.addObject("loginName", userSession.getLoginName());
                view.addObject("showMessage", userSession.getShowMessage());
                view.addObject("msgReceiveManage",loginService.showMsgReceiveManage(userSession.getUserId())?"1":"0");
                JSONArray resArray;
                resArray = new JSONArray();
                resArray = this.loginService.getUserRes(userSession.getUserId());
                view.addObject("data", resArray.toJSONString());
                view.addObject("homePage", userSession.getHomePage());
            }
        }
        view.setViewName(page);
        return view;
    }
    
    /**
     * 
     * <p>Description: 修改密码</p>
     * @param request 请求
     * @param response 响应
     * @return 修改结果
     */
    @RequestMapping(value = "/main/modifyPass.mvc")
    @ResponseBody
    public Map<String, Object> modifyPass(HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map;
        map = new HashMap<String, Object>();
        String loginName;
        loginName = request.getParameter("loginName");
        SysUser user;
        user = this.loginService.findUser(loginName);
        if (user != null) {
            String oldPass;
            oldPass = request.getParameter("oldpass");
            String pass;
            pass = MD5Util.getDigest(oldPass);
            if (pass.equals(user.getPass())) {
                String newpass;
                newpass = request.getParameter("newpass");
                user.setPass(MD5Util.getDigest(newpass));
                try {
                    map.put("msg", this.loginService.modifyPass(user));
                } catch (ServiceException e) {
                    //修改异常
                    e.printStackTrace();
                    map.put("msg", "error");
                }
            } else {
                //旧密码有误
                map.put("msg", "wrong");
            }
        } else {
            map.put("msg", "error");
        }
        return map;
    }
    
    @RequestMapping(value = "/main/checkLoginStatus.mvc")
    @ResponseBody
    public Map<String, Object> checkLoginStatus(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, Object> map;
        map = new HashMap<String, Object>();
        HttpSession currentSession;
        currentSession = request.getSession();
        String loginName = String.valueOf(currentSession.getAttribute("sys.userName"));
        if(StringUtils.isNotEmpty(loginName)) {
            if(!this.loginService.getAccountValidity(loginName)){
                map.put("msg", "accountExpired");
                return map;
            }
        } 
        //if (StrUtil.isEmpty(loginName) || this.checkLoginSeize(this.getIpAddress(request), loginName)) {
        if (StrUtil.isEmpty(loginName)) {
            map.put("msg", "loginSeize");
        } else {
            map.put("msg", "success");
        }
        return map;
    }
    
    /**
     * 
     * <p>Description: 验证是否重复登陆</p>
     * @param ip 登陆ip
     * @return 判断标志
     */
    private Boolean checkLoginSeize(String ip, String loginName) {
        if (LoginAction.UserPool.containsKey(loginName) &&
                !ip.equals(LoginAction.UserPool.get(loginName))) {
            return true;
        }
        return false;
    }
}
